﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace CPPEI.ETL.Domain.TaskProxy
{
    public static class TaskProxyManager
    {
        public static string s_taskDirectory;

        /// <summary>
        /// monitor使用的初始化方法，一定不要调用错
        /// </summary>
        /// <param name="taskDirectory"></param>
        public static void Init4Monitor(string taskDirectory)
        {
            s_taskDirectory = taskDirectory;
        }

        public static void Init(string taskDirectory)
        {
            s_taskDirectory = taskDirectory;

            // 扫描任务，更细任务目录的文件
            Services.TaskService taskService = new Services.TaskService();
            using(EtlDbContext dbContext = new EtlDbContext())
            {
                ListResult<Guid> serResult = taskService.GetTaskIdList(dbContext);
                if (serResult.IsSuccess)
                {
                    #region 删除多余的文件
                    string[] files = null;
                    
                    if(Directory.Exists(s_taskDirectory))
                    {
                        files = Directory.GetFiles(s_taskDirectory);
                        for (int index = 0; index < files.Length; index++)
                        {
                            FileInfo fileInfo = new FileInfo(files[index]);

                            bool hasTask = false;
                            for (int taskIndex = 0; taskIndex < serResult.Data.Count; taskIndex++)
                            {
                                string taskFile = string.Format("{0}.xml", serResult.Data[taskIndex]);
                                if (string.Equals(fileInfo.Name, taskFile))
                                {
                                    hasTask = true;
                                    break;
                                }
                            }
                            if (!hasTask)
                            {
                                // 删除任务文件
                                File.Delete(fileInfo.FullName);
                                Logger.WarningToTag(Library.LogTAG, string.Format("删除任务文件:{0}", fileInfo.FullName));
                            }
                        }
                    }
                    #endregion

                    #region 生成不存在文件的任务
                    for (int index = 0; index < serResult.Data.Count; index++)
                    {
                        Guid taskId = serResult.Data[index];
                        string filePath = string.Format("{0}{1}.xml", s_taskDirectory, taskId);

                        if (!File.Exists(filePath))
                        {
                            Logger.WarningToTag(Library.LogTAG, string.Format("重新为任务:{0}生成任务文件", taskId));
                            // 生成任务文件
                            Entities.ETask eTask = new EntityRepository<Entities.ETask>(dbContext).Get(p => p.Id == taskId);
                            List<Entities.ETaskRunMode> eRunModeList = new EntityRepository<Entities.ETaskRunMode>(dbContext).GetList(p => p.TaskId == taskId);
                            
                            try
                            {
                                Save(eTask, eRunModeList);
                            }
                            catch(Exception ex)
                            {
                                Logger.ErrorToTag(Library.LogTAG, string.Format("保存任务:{0}文件出错", eTask.Id));
                            }
                        }
                    }
                    #endregion
                }
            }

            Logger.InfoToTag("TaskProxy", "TaskProxyManager.Init Finished!");
        }

        /// <summary>
        /// 保存任务文件,如果任务的执行模式是手动模式和事件模式，那么则不生成任务文件
        /// </summary>
        /// <param name="eTask"></param>
        /// <param name="runModes"></param>
        public static void Save(CPPEI.ETL.Domain.Entities.ETask eTask, List<Entities.ETaskRunMode> runModes)
        {
            if(runModes==null || runModes.Count == 0)
            {
                return;
            }
            if(runModes[0].Mode == DEF.TaskRunMode.Manual || runModes[0].Mode == DEF.TaskRunMode.Event)
            {
                return;
            }

            string filePath = string.Format("{0}{1}.xml", s_taskDirectory, eTask.Id);
            FileInfo fileInfo = new FileInfo(filePath);

            if(!fileInfo.Directory.Exists)
            {
                fileInfo.Directory.Create();
            }

            XmlDocument xmlDoc = new XmlDocument();
            XmlElement xTask = xmlDoc.CreateElement("Task");

            XmlElement xId = xmlDoc.CreateElement("Id");
            xId.InnerText = eTask.Id.ToString();
            xTask.AppendChild(xId);

            XmlElement xService = xmlDoc.CreateElement("Service");
            xService.InnerText = eTask.DtSerId.ToString();
            xTask.AppendChild(xService);

            XmlElement xSource = xmlDoc.CreateElement("Source");
            xSource.InnerText = eTask.DtSourceId.ToString();
            xTask.AppendChild(xSource);

            XmlElement xTaskRunMode = xmlDoc.CreateElement("RunMode");
            xTaskRunMode.InnerText = eTask.RunMode.ToString();
            xTask.AppendChild(xTaskRunMode);

            XmlElement xRunModes = xmlDoc.CreateElement("RunModes");
            xTask.AppendChild(xRunModes);
            for (int index = 0; index < runModes.Count; index++)
            {
                Entities.ETaskRunMode runMode = runModes[index];

                XmlElement xRunMode = xmlDoc.CreateElement("RunMode");

                XmlElement xMode = xmlDoc.CreateElement("Mode");
                xMode.InnerText = runMode.Mode.ToString();
                xRunMode.AppendChild(xMode);

                if(runMode.Mode == CPPEI.ETL.Domain.DEF.TaskRunMode.Timer)
                {
                    XmlElement xTimerBeginTime = xmlDoc.CreateElement("TimerBeginTime");
                    xTimerBeginTime.InnerText = runMode.TimerBeginTime.Value.ToString();
                    xRunMode.AppendChild(xTimerBeginTime);

                    XmlElement xTimerInterval = xmlDoc.CreateElement("TimerInterval");
                    xTimerInterval.InnerText = runMode.TimerInterval.Value.ToString();
                    xRunMode.AppendChild(xTimerInterval);

                    XmlElement xTimerIntervalMode = xmlDoc.CreateElement("TimerIntervalMode");
                    xTimerIntervalMode.InnerText = runMode.TimerIntervalMode.Value.ToString();
                    xRunMode.AppendChild(xTimerIntervalMode);
                }
                else if (runMode.Mode == CPPEI.ETL.Domain.DEF.TaskRunMode.Alarm)
                {
                    XmlElement xAlarmMode = xmlDoc.CreateElement("AlarmMode");
                    xAlarmMode.InnerText = runMode.AlarmMode.Value.ToString();
                    xRunMode.AppendChild(xAlarmMode);

                    XmlElement xAlarmClock = xmlDoc.CreateElement("AlarmClock");
                    xAlarmClock.InnerText = runMode.AlarmClock.Value.ToString();
                    xRunMode.AppendChild(xAlarmClock);
                }
                else if (runMode.Mode == CPPEI.ETL.Domain.DEF.TaskRunMode.Event)
                {
                    XmlElement xEventName = xmlDoc.CreateElement("EventName");
                    xEventName.InnerText = runMode.EventName;
                    xRunMode.AppendChild(xEventName);
                }

                xRunModes.AppendChild(xRunMode);
            }

            xmlDoc.AppendChild(xTask);

            xmlDoc.Save(filePath);
        }

        /// <summary>
        /// 删除任务文件
        /// </summary>
        /// <param name="task"></param>
        public static void Delete(Task task)
        {
            string filePath = string.Format("{0}{1}.xml", s_taskDirectory, task.Id);

            File.Delete(filePath);
        }

        public static void Delete(Guid taskId)
        {
            string filePath = string.Format("{0}{1}.xml", s_taskDirectory, taskId);

            File.Delete(filePath);
        }

        /// <summary>
        /// 获取数据文件
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static Task Load(string filePath)
        {
            FileInfo fileInfo = new FileInfo(filePath);

            if (!fileInfo.Directory.Exists)
            {
                fileInfo.Directory.Create();
            }

            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(filePath);

            Task task = new Task();

            task.ModifiedTime = fileInfo.CreationTime;

            XmlNode xTask = xmlDoc.SelectSingleNode("./Task");

            XmlNode xId = xTask.SelectSingleNode("./Id");
            task.Id = new Guid(xId.InnerText);

            XmlNode xService = xTask.SelectSingleNode("./Service");
            task.ServiceId = new Guid(xService.InnerText);

            XmlNode xSource = xTask.SelectSingleNode("./Source");
            task.SourceId = new Guid(xSource.InnerText);

            XmlNode xTaskRunMode = xTask.SelectSingleNode("./RunMode");
            task.RunMode = Convert.ToInt32(xTaskRunMode.InnerText);

            XmlNodeList xRunModes = xTask.SelectNodes("./RunModes/RunMode");
            for (int index = 0; index < xRunModes.Count; index++)
            {
                XmlNode xRunMode = xRunModes[index];

                TaskRunMode runMode = new TaskRunMode();

                XmlNode xMode = xRunMode.SelectSingleNode("./Mode");
                runMode.Mode = Convert.ToInt32(xMode.InnerText);

                if (runMode.Mode == CPPEI.ETL.Domain.DEF.TaskRunMode.Timer)
                {
                    XmlNode xTimerBeginTime = xRunMode.SelectSingleNode("./TimerBeginTime");
                    runMode.TimerBeginTime = Convert.ToDateTime(xTimerBeginTime.InnerText);

                    XmlNode xTimerInterval = xRunMode.SelectSingleNode("./TimerInterval");
                    runMode.TimerInterval = Convert.ToInt32(xTimerInterval.InnerText);

                    XmlNode xTimerIntervalMode = xRunMode.SelectSingleNode("./TimerIntervalMode");
                    runMode.TimerIntervalMode = Convert.ToInt32(xTimerIntervalMode.InnerText);
                }
                else if (runMode.Mode == CPPEI.ETL.Domain.DEF.TaskRunMode.Alarm)
                {
                    XmlNode xAlarmMode = xRunMode.SelectSingleNode("./AlarmMode");
                    runMode.AlarmMode = Convert.ToInt32(xAlarmMode.InnerText);

                    XmlNode xAlarmClock = xRunMode.SelectSingleNode("./AlarmClock");
                    runMode.AlarmClock = Convert.ToDateTime(xAlarmClock.InnerText);
                }
                else if (runMode.Mode == CPPEI.ETL.Domain.DEF.TaskRunMode.Event)
                {
                    XmlNode xEventName = xRunMode.SelectSingleNode("./EventName");
                    runMode.EventName = xEventName.InnerText;
                }

                task.RunModes.Add(runMode);
            }

            return task;
        }

        /// <summary>
        /// 扫描目录获取所有的项目文件列表
        /// </summary>
        /// <returns></returns>
        public static List<TaskFile> Scan()
        {
            List<TaskFile> taskFiles = new List<TaskFile>();

            if(!Directory.Exists(s_taskDirectory))
            {
                return taskFiles;
            }

            string[] files = null;
            
            try
            {
                files = Directory.GetFiles(s_taskDirectory);
            }
            catch(Exception ex)
            {
                Logger.ErrorToTag(Library.LogTAG, string.Format("从目录:{0}读取任务文件失败出错,ex:{1}", s_taskDirectory, ex));
            }

            if(files != null)
            {
                for (int index = 0; index < files.Length; index++)
                {
                    FileInfo fileInfo = new FileInfo(files[index]);

                    TaskFile tFile = new TaskFile();
                    tFile.Id = new Guid(fileInfo.Name.Replace(fileInfo.Extension, string.Empty));
                    tFile.ModifiedTime = fileInfo.CreationTime;
                    tFile.Path = fileInfo.FullName;

                    taskFiles.Add(tFile);
                }
            }

            return taskFiles;
        }
    }
}
